<?php

/**
 * Description of FormRecorder
 *
 * @author bonfiglio
 * @todo Commenter !!!
 */
class FormRecorder {

    public $formFields = array();
    public $return = array('errors' => array(), 'success' => false);
    public $values = array(
        'table' => '', // La table mysql dans laquelle on enregistre les données
        'success' => '' // Le message à afficher lorsque le formulaire est validé
    );
    private $options = array();
    public $post = array();
    private $groups = array();

    public function __construct($formFields, $options = array()) {
        $this->formFields = $formFields;
        $this->options = $options;
    }

    private function filterMultipleValueField($fieldName, $values,$errorMessage) {
        $return = array(
            'values' => array(),
            'errors' => array()
        );
        //Filtre + option
        if (isset($this->formFields[$fieldName]) && count($values)) {

            foreach ($values as $key => $valueDraft) {
                $value = $this->filterValueField($fieldName, $valueDraft);
                $return['values'][$key] = $value;
                if (!strlen($value)) {
                    $return['errors'][$key] = $errorMessage;
                }
            }
        }
        return $return;
    }

    private function filterValueField($fieldName, $value) {

        //Filtre + option
        if (isset($this->formFields[$fieldName])) {
            
            $value = trim($value);
            
            $DataFilter = new DataFilter($value, $this->formFields[$fieldName]);

            $value = (in_array($DataFilter->filter, array(FILTER_VALIDATE_EMAIL, FILTER_SANITIZE_EMAIL, FILTER_SANITIZE_STRING, FILTER_CALLBACK))) ? strtolower($DataFilter->getValue()) : $DataFilter->getValue();
        }
        return $value;
    }

    public function isMultiple($fieldName) {
        if (isset($this->formFields[$fieldName]) && array_key_exists('multiple', $this->formFields[$fieldName])) {
            return (boolean) $this->formFields[$fieldName]['multiple'];
        }
        return false;
    }

    public function validatePost($post) {

        $this->post = $post;
        $this->groups = array();

        if (count($this->post)) {

            $requiredGroups = array();
            $requiredGroupsExclude = array();
            $this->values = array();

            //nettoyage du post + gestion erreur
            foreach ($this->formFields as $field => $attributs) {
                $value = false;
                $errorMessage = isset($attributs['error']) ? $attributs['error'] : '';
                
                $multiple = $this->isMultiple($field);
                if ($multiple) {
                    $value = $this->filterMultipleValueField($field, (isset($this->post[$field]) ? $this->post[$field] : null),$errorMessage);
                    $this->values[$field] = $value['values'];
                } else {
                    $value = $this->filterValueField($field, (isset($this->post[$field]) ? $this->post[$field] : null));
                    $this->values[$field] = $value;
                }

                
                //Attribut requis : il suffit d'un vide pour être en erreur
                $required = isset($attributs['required']) ? $attributs['required'] : false;

                //Attribut group : regroupe les champs à étendre un la ligne à insérer ==> array('group', 'champ a substituer')
                $group = isset($attributs['group']) ? $attributs['group'] : array();


                if (count($group) == 2) {
                    if (!isset($this->groups[$group[0]])) {
                        $this->groups[$group[0]] = array();
                    }
                    $this->groups[$group[0]][$group[1]] = $value;
                    if ($required) {
                        if (empty($this->groups[$required][$group[1]])) {
                            if (!isset($requiredGroups[$required])) {
                                $requiredGroups[$required] = array();
                            }
                            $requiredGroups[$required][$field] = $attributs['error'];
                            $required = false;
                        }
                    } else if (!empty($value)) {
                        if (!isset($requiredGroupsExclude[$group[0]])) {
                            $requiredGroupsExclude[$group[0]] = array();
                        }
                        $requiredGroupsExclude[$group[0]][$group[1]] = $value;
                    }
                } else {
                    $this->post[$field] = $value;
                }
                
                if ($multiple && count($value['errors'])) {
                    $this->return['errors'][$field] = $value['errors'];
                }elseif ($required && !strlen($value)) {
                    $this->return['errors'][$field] = $errorMessage;
                }
            }

            //pre($this->values);
            //vérification des groupements
            if (count($requiredGroups)) {
                foreach ($requiredGroups as $group => $fields) {
                    $groupsInSuccess = array_filter($groups[$group]);
                    $groupsExclude = array_filter($requiredGroupsExclude[$group]);
                    $fieldsFilled = array_diff_key($groupsInSuccess, $groupsExclude);
                    if (isset($groups[$group]) && count($fieldsFilled)) {
                        $this->return['errors'] = array_merge($this->return['errors'], $fields);
                    }
                }
            }
        }
        $this->setReturn();
        return $this;
    }

    public function updatePost($condition, $fieldName, $value) {
        if (strlen($condition) > 0 && isset($this->formFields[$fieldName])) {
            $value = $this->filterValueField($fieldName, $value);
            $Database = Database::factory($this->options['database']);
            $sql = 'UPDATE `' . $this->options['table'] . '`
                    SET
                    ' . $fieldName . ' = ' . $Database->escapeWithoutQuotes($value) . '
                    WHERE ' . $condition . ' ;';
            return $Database->Execute($sql);
            ;
        }
    }

    public function savePost($force = false) {
        if ((!$this->hasErrors() && strlen($this->options['table'])) || $force) {

            $Database = Database::factory($this->options['database']);

            $fields = $values = array();

            foreach ($this->post as $key => $value) {
                //puisqu'on est en insert, on n'insert que les champs renseignés ...
                if (isset($this->formFields[$key])) {
                    if (strlen($value)) {
                        $fields[] = $key;
                        $values[$key] = $Database->escapeWithoutQuotes($value);
                    }
                }
            }
            $sql = '
            INSERT INTO `' . $this->options['table'] . '`(' . implode(',', $fields) . ')
            VALUES (' . implode(',', $values) . ');';

            if (count($this->groups)) {
                foreach ($this->groups as $group => $fields) {
                    $fields = array_filter($fields);
                    $groupsExclude = array_filter($requiredGroupsExclude[$group]);
                    $fieldsFilled = array_diff_key($fields, $groupsExclude);
                    if (count($fieldsFilled)) {
                        $nfields = array();
                        $nvalues = array();
                        foreach ($values as $field => $value) {
                            $nfields[] = $field;
                            if (substr($field, 0, 5) == 'custom' && $field != 'custom0') {
                                $nvalues[$field] = 'NULL';
                            } else if (isset($fields[$field])) {
                                $nvalues[$field] = $Database->escapeWithoutQuotes($fields[$field]);
                            } else if (strlen($value)) {
                                $nvalues[$field] = $value;
                            }
                        }
                        $sql .= '
            INSERT INTO `' . $this->options['table'] . '`(' . implode(',', $nfields) . ')
            VALUES (' . implode(',', $nvalues) . ');';
                    }
                }
            }
            $Database->Execute($sql);
            return $Database->LastId();
        }
        return false;
    }

    public function hasErrors() {
        return count($this->getErrors());
    }

    public function getErrors() {
        return $this->return['errors'];
    }

    public function getValues() {
        return $this->values;
    }

    public function setReturn() {
        if (!$this->hasErrors()) {
            $this->return['success'] = isset($this->options['success']) && !empty($this->options['success']) ? $this->options['success'] : 'Données enregistrés';
        }
    }

    public function getReturn() {
        return $this->return;
    }

}

?>
